立创梁山派GD32F470ZGT6

您所在的位置:网站首页 gd32 uart dma 立创梁山派GD32F470ZGT6

立创梁山派GD32F470ZGT6

2023-11-23 12:04| 来源: 网络整理| 查看: 265

准备

屏幕 使用SPI接口的1.69寸240x280TFT彩屏. 主控 使用立创·梁山派GD32F470ZGT6.

屏幕与主控的连接 在这里插入图片描述

使用硬件SPI+DMA的方式刷屏。

一般我们拿到一个屏幕首先需要移植厂商提供的官方代码进行亮屏测试。这里我们就不使用DMA配置了,只用最基本Io模拟SPI或者硬件SPI的方法,先将屏幕点亮清屏或者整屏刷新颜色就行。 移植好代码后要仔细观察颜色刷新是否正确(色差),显示方法是否正确(横屏竖屏),颜色数据刷新是否正常(错,漏,闪烁)。    设计连线符合器件要求无误的情况下存在问题,就需要查看手册,通过手册发现GD32F470的SPI存在FIFO,所以发送数据的结尾需要等待数据发送完成再释放片选。否则容易导致屏幕显示出现问题(一般都是以缓冲区是否为空当作传输的判断标准,以此提高发送效率)。    在这里插入图片描述 在这里插入图片描述   屏幕的代码初始化需要根据屏幕厂商提供的初始化代码就行移植以减少开发难度。

硬件SPI初始化

需要使能硬件SPI的DMA发送功能。

void lcd_gpio_config(void) { spi_parameter_struct spi_init_struct; rcu_periph_clock_enable(RCU_LCD_SCL); rcu_periph_clock_enable(RCU_LCD_SDA); rcu_periph_clock_enable(RCU_LCD_CS); rcu_periph_clock_enable(RCU_LCD_DC); rcu_periph_clock_enable(RCU_LCD_RES); rcu_periph_clock_enable(RCU_LCD_BLK); rcu_periph_clock_enable(RCU_SPI_HARDWARE); // 使能SPI /* 配置 SPI的SCK GPIO */ gpio_af_set(PORT_LCD_SCL, LINE_AF_SPI, GPIO_LCD_SCL); gpio_mode_set(PORT_LCD_SCL, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_LCD_SCL); gpio_output_options_set(PORT_LCD_SCL, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_SCL); gpio_bit_set(PORT_LCD_SCL,GPIO_LCD_SCL); /* 配置 SPI的MOSI GPIO */ gpio_af_set(PORT_LCD_SDA, LINE_AF_SPI, GPIO_LCD_SDA); gpio_mode_set(PORT_LCD_SDA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_LCD_SDA); gpio_output_options_set(PORT_LCD_SDA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_SDA); gpio_bit_set(PORT_LCD_SDA, GPIO_LCD_SDA); /* 配置DC */ gpio_mode_set(PORT_LCD_DC,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_LCD_DC); gpio_output_options_set(PORT_LCD_DC,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_LCD_DC); gpio_bit_write(PORT_LCD_DC, GPIO_LCD_DC, SET); /* 配置RES */ gpio_mode_set(PORT_LCD_RES,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_LCD_RES); gpio_output_options_set(PORT_LCD_RES,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_LCD_RES); gpio_bit_write(PORT_LCD_RES, GPIO_LCD_RES, SET); /* 配置BLK */ gpio_mode_set(PORT_LCD_BLK, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_LCD_BLK); gpio_output_options_set(PORT_LCD_BLK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_BLK); gpio_bit_write(PORT_LCD_BLK, GPIO_LCD_BLK, SET); /* 配置CS */ gpio_mode_set(PORT_LCD_CS,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_LCD_CS); gpio_output_options_set(PORT_LCD_CS,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_LCD_CS); gpio_bit_write(PORT_LCD_CS, GPIO_LCD_CS, SET); // 配置 SPI 参数 spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;// 传输模式全双工 spi_init_struct.device_mode = SPI_MASTER; // 配置为主机 spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; // 8位数据 spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; // 极性高相位2 spi_init_struct.nss = SPI_NSS_SOFT; // 软件cs spi_init_struct.prescale = SPI_PSC_2; // 2分频 spi_init_struct.endian = SPI_ENDIAN_MSB; // 高位在前 spi_init(PORT_SPI, &spi_init_struct); //使能DMA发送 spi_dma_enable(PORT_SPI,SPI_DMA_TRANSMIT); // 使能 SPI spi_enable(PORT_SPI); //初始化DMA dma_spi_init(); } 配置DMA

使用DMA的通用流程都是先配置外设对应的DMA及通道,再配置自动或者软件触发DMA搬运方向。不过,我们需要根据屏幕的像素确定要传输的数据量,DMA的最大数据传输量为65535。而我使用的是1.69寸屏幕,像素为240x280,即全部像素为240 * 280 = 67200,已经超过了最大DMA传输量。所以将全部像素数据分两次进行传输,即67200 / 2 = 33600。但是,我的数据宽度设置为了8位,即一次传输8位的数据。而我使用的1.69寸屏,是TFT彩屏,一个像素点需要16位的彩色数据。DMA设置为8位传输,而屏幕一个像素是16位的数据,故实际的传输数据量为全部像素大小*2!即67200 * 2=134400。所以我们想要显示一帧图像,需要传输4次!     在这里插入图片描述 DMA通道的说明 我硬件SPI使用的是SPI0(需要根据使用引脚确定的),根据数据手册中关于DMA的请求表可以知道,要想使用DMA搬运硬件SPI0的数据,只可以通过DMA1的通道3,或者通道5。案例中选择的是DMA1的通道3。 在这里插入图片描述

void dma_spi_init(void) { dma_single_data_parameter_struct dma_init_struct; /* 使能DMA1时钟 */ rcu_periph_clock_enable(RCU_DMA1); /* 初始化DMA1的通道3 */ dma_deinit(DMA1, DMA_CH3); dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; //内存往外设 dma_init_strucmory0_addr = (uint32_t)0; //内存地址 dma_init_strucmory_inc = DMA_MEMORY_INCREASE_ENABLE; //开启内存地址增量 dma_init_struct.periph_memory_width = DMA_MEMORY_WIDTH_8BIT; //内存数据宽度 dma_init_struct.number = LCD_W * LCD_H / 2; //数据量 240*280/2 = 67200/2 = 33600 dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(PORT_SPI) ; //外设地址 dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; //关闭外设地址增量 dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; //优先级高 dma_single_data_mode_init(DMA1, DMA_CH3, &dma_init_struct); //将以上参数填入DMA1的通道3 // 禁用DMA循环模式 dma_circulation_disable(DMA1, DMA_CH3); // DMA通道外设选择 011 dma_channel_subperipheral_select(DMA1, DMA_CH3, DMA_SUBPERI3); // 启用DMA1传输完成中断 dma_interrupt_enable(DMA1, DMA_CH3, DMA_CHXCTL_FTFIE); // 配置中断优先级(必须为最高) nvic_irq_enable(DMA1_Channel3_IRQn, 0, 0); // 失能DMA1的通道3 dma_channel_disable(DMA1, DMA_CH3); } 开启显示

DMA初始化配置后,需要再次传输的快捷操作为:清除标志位,设置传输量,设置传输地址,开始传输。 关于清除全部中断标志位的解释 因为我使用到的硬件SPI的是DMA1的通道3,实际上只需要往DMA_INTC0寄存器写入( 0x2f



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3